﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Reflection;
using System.Security.Cryptography;
using WxLib.Pay;
using System.IO;

namespace WxLib.Common
{
    /// <summary>
    /// 微信API常用工具类
    /// </summary>
    public class WxUtil
    {

        public static string SHA1Sign(string data)
        {
            byte[] temp1 = Encoding.UTF8.GetBytes(data);

            SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
            byte[] temp2 = sha.ComputeHash(temp1);
            sha.Clear();

            // 注意， 不能用这个
            //string output = Convert.ToBase64String(temp2);

            string output = BitConverter.ToString(temp2);
            output = output.Replace("-", "");
            output = output.ToLower();
            return output;
        }

        /** 获取大写的MD5签名结果 */
        public static string GetMD5(string encypStr, string charset)
        {
            string retStr;
            MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();
            //创建md5对象
            byte[] inputBye;
            byte[] outputBye;
            //使用GB2312编码方式把字符串转化为字节数组．
            try
            {
                inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr);
            }
            catch (Exception)
            {
                inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
            }
            outputBye = m5.ComputeHash(inputBye);
            retStr = System.BitConverter.ToString(outputBye);
            retStr = retStr.Replace("-", "").ToUpper();
            return retStr;
        }

        /// <summary>
        /// 随机串
        /// </summary>
        public static string GetNoncestr()
        {
            return Guid.NewGuid().ToString().Replace("-", "");
            //Random random = new Random();
            //return GetMD5(random.Next(1000).ToString(), "GBK").ToLower().Replace("s", "S");
        }

        /// <summary>
        /// 时间截，自1970年以来的秒数
        /// </summary>
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        /// <summary>
        /// 获取签名
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="options">参数对象</param>
        /// <param name="key">店面KEY</param>
        /// <returns>签名</returns>
        public static string GetSign<T>(T options, string key)
        {
            string sign = string.Empty;
            Type type = typeof(T);
            PropertyInfo[] propertyInfos = type.GetProperties();
            SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();
            foreach (PropertyInfo pi in propertyInfos)
            {
                string name = pi.Name;
                if (name.ToLower() == "sign")
                    continue;
                object valObj = pi.GetValue(options);
                if (valObj != null)
                    sParams.Add(name, valObj.ToString());
            }
            return GetSign(sParams, key);
        }

        /// <summary>
        /// 获取微信签名
        /// </summary>
        /// <param name="sParams">键排序参数集合</param>
        /// <returns>签名</returns>
        public static string GetSign(SortedDictionary<string, string> sParams, string key)
        {
            string sign = string.Empty;
            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair<string, string> temp in sParams)
            {
                if (temp.Value == "" || temp.Value == null || temp.Key.ToLower() == "sign")
                    continue;
                sb.Append(temp.Key.Trim() + "=" + temp.Value.Trim() + "&");
            }
            sb.Append("key=" + key.Trim() + "");
            string signkey = sb.ToString();
            sign = GetMD5(signkey, "utf-8");
            return sign;
        }

        public static string DecodeUserInfo(string encryptedData, string iv, string sessionkey)
        {
            byte[] iv2 = Convert.FromBase64String(iv);

            if (string.IsNullOrEmpty(encryptedData)) return "";
            Byte[] toEncryptArray = Convert.FromBase64String(encryptedData);

            RijndaelManaged rm = new RijndaelManaged
            {
                Key = Convert.FromBase64String(sessionkey),
                IV = iv2,
                Mode = CipherMode.CBC,
                Padding = PaddingMode.PKCS7
            };

            ICryptoTransform cTransform = rm.CreateDecryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return Encoding.UTF8.GetString(resultArray);

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="encryptedDataStr"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        public static string AES_decrypt(string encryptedDataStr, string key, string iv)
        {
            RijndaelManaged rijalg = new RijndaelManaged();
            //-----------------    
            //设置 cipher 格式 AES-128-CBC    

            rijalg.KeySize = 128;

            rijalg.Padding = PaddingMode.PKCS7;
            rijalg.Mode = CipherMode.CBC;

            rijalg.Key = Convert.FromBase64String(key);
            rijalg.IV = Convert.FromBase64String(iv);


            byte[] encryptedData = Convert.FromBase64String(encryptedDataStr);
            //解密    
            ICryptoTransform decryptor = rijalg.CreateDecryptor(rijalg.Key, rijalg.IV);

            string result;

            using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {

                        result = srDecrypt.ReadToEnd();
                    }
                }
            }

            return result;
        }


    }
}